package data.platform.mock;

import data.platform.common.domain.MetricValue;
import data.platform.common.event.MetricValueEvent;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
@RequiredArgsConstructor
public class MockDataPoint {

    final ApplicationContext applicationContext;

    private List<IpRange> ipRanges;

    private ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;

    @PostConstruct
    public void init() {
        ipRanges = new ArrayList<>();
        ipRanges.add(IpRange.builder().startIp("12.0.0.0")
                .endIp("12.0.0.10")
                .moType("NetworkDevice")
                .location("Shanghai")
                .room("YiShan@700")
                .metrics(Arrays.asList("CPU", "MEM"))
                .build());

        ipRanges.add(IpRange.builder().startIp("13.0.0.0")
                .endIp("13.0.0.10")
                .moType("Windows")
                .location("BeiJin")
                .room("HaiDing@1024")
                .metrics(Arrays.asList("CPU_LOAD", "MEM_LOAD", "OSCPU_CPU_Load"))
                .build());

        scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1);

        sendDataPoint();
    }

    public void sendDataPoint() {
        scheduledThreadPoolExecutor.scheduleAtFixedRate(() -> {
            try {
                List<MetricValue> metricValues = new ArrayList<>();
                for (IpRange ipRange : ipRanges) {
                    List<String> ipRanges = createIpRange(ipRange.getStartIp(), ipRange.getEndIp());
                    for (String ip : ipRanges) {
                        ipRange.getMetrics().forEach(metricName -> {
                            double value = Double.valueOf(ThreadLocalRandom.current().nextInt(100));
                            MetricValue metricValue = MetricValue.builder()
                                    .metric(metricName)
                                    .tag(createTag(ip, ipRange.getLocation(), ipRange.getRoom(), ipRange.getMoType()))
                                    .eventTime(LocalDateTime.now())
                                    .value(value)
                                    .eventValue("{\"value\": " + value + " }")
                                    .build();
                            metricValues.add(metricValue);

                        });

                        // 故障点 0：代表故障 >0: 代表非故障
                        boolean faultStatus = ThreadLocalRandom.current().nextBoolean();
                        double value = faultStatus ? 0.0 : ThreadLocalRandom.current().nextInt(100) + 1;
                        MetricValue metricValue = MetricValue.builder()
                                .metric("UpTime")
                                .tag(createTag(ip, ipRange.getLocation(), ipRange.getRoom(), ipRange.getMoType()))
                                .eventTime(LocalDateTime.now())
                                .value(value)
                                .eventValue("{\"value\": " + value + " }")
                                .build();
                        metricValues.add(metricValue);
                    }
                }
                applicationContext.publishEvent(new MetricValueEvent(metricValues));
            } catch (Exception ex) {
                log.error("", ex);
            }
        }, 0, 20, TimeUnit.SECONDS);
    }

    private List<String> createIpRange(String startIp, String endIp) {
        List<String> ipRanges = new ArrayList<>();
        String[] startParts = startIp.split("(?<=\\.)(?!.*\\.)");
        String[] endParts = endIp.split("(?<=\\.)(?!.*\\.)");

        int first = Integer.parseInt(startParts[1]);
        int last = Integer.parseInt(endParts[1]);

        for (int i = first; i <= last; i++) {
            ipRanges.add(startParts[0] + i);
        }
        return ipRanges;
    }

    private Map<String, String> createTag(String ip, String location, String room, String moType) {
        Map<String, String> tags = new HashMap<>();
        tags.put("ip", ip);
        tags.put("location", location);
        tags.put("room", room);
        tags.put("moc", moType);
        return tags;
    }

}
